package de.szut.ita13.rs.wave.main;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;

import de.szut.ita13.rs.wave.controller.Controller;
import de.szut.ita13.rs.wave.controller.KeyInput;
import de.szut.ita13.rs.wave.entities.BasicEnemy;
import de.szut.ita13.rs.wave.entities.Player;
import de.szut.ita13.rs.wave.entity.Type;
import de.szut.ita13.rs.wave.hud.HUD;
import de.szut.ita13.rs.wave.spawn.Spawner;


public class Game extends Canvas implements Runnable {

	private static final long serialVersionUID = 1L;
	
	public static final int WIDTH = 640, HEIGHT = WIDTH / 12 * 9;
	public static final int BUFFERS = 3;
	public static final Color BACKGROUND_COLOR = Color.BLACK;
	
	private Thread gameThread;
	private boolean running = false;
	
	private Controller controller;
	private HUD hud;
	private Spawner spawner;
	
	public Game() {
		
		controller = new Controller();
		hud = new HUD();
		spawner = new Spawner(controller, hud);
		
		this.addKeyListener(new KeyInput(controller));
		new Window(WIDTH, HEIGHT, "Epic Wave", this);
		
		
		controller.addEntity(new Player(WIDTH / 2 - 32, HEIGHT / 2 - 32, Type.Player, controller));
		controller.addEntity(new BasicEnemy(WIDTH / 2 - 32, HEIGHT / 2 - 32, Type.BasicEnemy, controller));
		
	}

	public synchronized void start() {
		gameThread = new Thread(this);
		gameThread.start();
		running = true;
	}
	
	public synchronized void stop() {
		try {
			gameThread.join();
			running = false;
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
	
	public void run() {
		this.requestFocus();
		long lastTime = System.nanoTime();
		double amountOfTicks = 60.0;
		double ns = 1000000000 / amountOfTicks;
		double delta = 0;
		long timer = System.currentTimeMillis();
		int frames = 0;
		while(running) {
			long now = System.nanoTime();
			delta += (now - lastTime) / ns;
			lastTime = now;
			while(delta >= 1) {
				tick();
				delta--;
			}
			if(running) {
				render();
			}
			frames++;
			
			if(System.currentTimeMillis() - timer > 1000) {
				timer += 1000;
				System.out.println("FPS: " + frames);
				frames = 0;
			}
		}
		stop();
	}
	
	private void tick() {
		controller.tick();
		hud.tick();
		spawner.tick();
		controller.runModificationLists();
	}
	
	private void render() {
		BufferStrategy bufferStrategy = this.getBufferStrategy();
		if(bufferStrategy == null) {
			this.createBufferStrategy(BUFFERS);
			return;
		}
		
		Graphics g = bufferStrategy.getDrawGraphics();
		
		
		g.setColor(BACKGROUND_COLOR);
		g.fillRect(0, 0, WIDTH, HEIGHT);
		
		
		controller.render(g);
		hud.render(g);
		
		g.dispose();
		bufferStrategy.show();
	}
	
	public static int clamp(int value, int min, int max) {
		if(value >= max)
			return value = max;
		else if(value <= min)
			return value = min;
		else
			return value;
	}
	
	public static void main(String[] args) {
		new Game();
	}

}
